// Functions associated with the MeshOrthographic class
//-----------------

//-----------------
// Includes libraries and other files
#include "MeshOrthographic.h"
//-----------------

//-----------------
//// CONSTRUCTOR - MeshOrthographic
MeshOrthographic::MeshOrthographic()
	: needs_releasing_( false)
{}

//// DESTRUCTOR - ~MeshOrthographic
MeshOrthographic::~MeshOrthographic() {
	device_ = nullptr;
	
	if( needs_releasing_)
		vertex_buffer->Release();
}
//-----------------

//-----------------
//// FUNCTION - render
// manipulate the mesh then call the private function to output it
void MeshOrthographic::render( LPDIRECT3DTEXTURE9 texture, float tx, float ty, float tz, float sx, float sy, float sz, float rx, float ry, float rz, const int& o) const {
	// Pre-conditions :- the device must exist
	assert( device_ != nullptr);

	// translate the object using parameters
	D3DXMATRIX translate_mat, scale_mat, rotX_mat, rotY_mat, rotZ_mat;
	D3DXMatrixIdentity( &translate_mat);
	D3DXMatrixIdentity( &scale_mat);
	D3DXMatrixIdentity( &rotX_mat);
	D3DXMatrixIdentity( &rotY_mat);
	D3DXMatrixIdentity( &rotZ_mat);

	D3DXMatrixTranslation(	&translate_mat,	tx-0.5, ty-0.5, tz);
	D3DXMatrixScaling(		&scale_mat,		sx, sy, sz);
	D3DXMatrixRotationX(	&rotX_mat,		D3DXToRadian( rx));
	D3DXMatrixRotationY(	&rotY_mat,		D3DXToRadian( ry));
	D3DXMatrixRotationZ(	&rotZ_mat,		D3DXToRadian( rz));

	D3DXMatrixMultiply(		&translate_mat, &scale_mat, &translate_mat);
	D3DXMatrixMultiply(		&translate_mat, &rotX_mat, &translate_mat);
	D3DXMatrixMultiply(		&translate_mat, &rotY_mat, &translate_mat);
	D3DXMatrixMultiply(		&translate_mat, &rotZ_mat, &translate_mat);
	device_->SetTransform(	D3DTS_WORLD, &translate_mat);

	render( texture, o);
}

//// FUNCTION - render
// manipulate the mesh then call the private function to output it
void MeshOrthographic::render( LPDIRECT3DTEXTURE9 texture, float tx, float ty, float tz, float sx, float sy, float sz, const int& o) const {
	// Pre-conditions :- the device must exist
	assert( device_ != nullptr);

	// translate the object using parameters
	D3DXMATRIX translate_mat, scale_mat;
	D3DXMatrixIdentity( &translate_mat);
	D3DXMatrixIdentity( &scale_mat);

	D3DXMatrixTranslation(	&translate_mat,	tx-0.5, ty-0.5, tz);
	D3DXMatrixScaling(		&scale_mat,		sx, sy, sz);
	D3DXMatrixMultiply(		&translate_mat, &scale_mat, &translate_mat);
	device_->SetTransform(	D3DTS_WORLD, &translate_mat);

	render( texture, o);
}

//// FUNCTION - render
// manipulate the mesh then call the private function to output it
void MeshOrthographic::render( LPDIRECT3DTEXTURE9 texture, float x, float y, float z, const int& o) const {
	// Pre-conditions :- the device must exist
	assert( device_ != nullptr);

	// translate the object using parameters
	D3DXMATRIX translate_mat;

	D3DXMatrixIdentity( &translate_mat);
	D3DXMatrixTranslation(	&translate_mat, x, y, 1.5f);
	device_->SetTransform(	D3DTS_WORLD, &translate_mat);

	render( texture, o);
}

//// FUNCTION - setup
// create the plane and save the device
HRESULT MeshOrthographic::setup( LPDIRECT3DDEVICE9 device) {
	// Pre-conditions :- the device must exist
	assert( device != nullptr);

	device_ = device;

	// Calculate the number of vertices required, and the size of the buffer to hold them.
	int vertices = 2 * 3;	// Six vertices for the square.
	int buffer_size = vertices * sizeof(CUSTOM_VERTEX);

	// Create the vertex buffer.
	if( FAILED( device->CreateVertexBuffer(buffer_size, 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT, &vertex_buffer, NULL))) {
		MessageBox( NULL, "Error Code: 006", "MeshOrthographic::MeshOrthographic", MB_OK);
		return E_FAIL;
	}

	// Create a pointer to the first vertex in the buffer.
	CUSTOM_VERTEX *p_vertices;
    if( FAILED( vertex_buffer->Lock(0, 0, (void**)&p_vertices, 0))) {
		MessageBox( NULL, "Error Code: 006", "MeshOrthographic::MeshOrthographic", MB_OK);
		return E_FAIL;
	}

	// Fill the vertex buffers with data...
	p_vertices[0].position.x = -0.5;
	p_vertices[0].position.y =  0.5;
	p_vertices[0].position.z =  0;
	p_vertices[0].u		  = 0;
	p_vertices[0].v		  = 0;
	
	p_vertices[1].position.x = 0.5;
	p_vertices[1].position.y = 0.5;
	p_vertices[1].position.z = 0;
	p_vertices[1].u		  = 1;
	p_vertices[1].v		  = 0;

	p_vertices[2].position.x = -0.5;
	p_vertices[2].position.y = -0.5;
	p_vertices[2].position.z =  0;
	p_vertices[2].u		  = 0;
	p_vertices[2].v	      = 1;

	p_vertices[3].position.x =  0.5;
	p_vertices[3].position.y = -0.5;
	p_vertices[3].position.z =  0;
	p_vertices[3].u		  = 1;
	p_vertices[3].v	      = 1;
	
	p_vertices[4].position.x = -0.5;
	p_vertices[4].position.y = -0.5;
	p_vertices[4].position.z =  0;
	p_vertices[4].u		  = 0;
	p_vertices[4].v	      = 1;

	p_vertices[5].position.x =  0.5;
	p_vertices[5].position.y =  0.5;
	p_vertices[5].position.z =  0;
	p_vertices[5].u		  = 1;
	p_vertices[5].v	      = 0;


	// Unlock the vertex buffer...
	vertex_buffer->Unlock();
	needs_releasing_ = true;

	return S_OK;
}

//// FUNCTION - render
// apply the texture and render the object
void MeshOrthographic::render( LPDIRECT3DTEXTURE9 texture, const int& opacity) const {
	// Pre-conditions :- the device must exist
	assert( device_ != nullptr);

	// the opacity also needs to be applied here however I don't have the code for it yet

	// Select the texture, and initialise the texture stage state...
	device_->SetTexture( 0, texture);
	device_->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	device_->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);

	// Render the contents of the vertex buffer.
	device_->SetStreamSource( 0, vertex_buffer, 0, sizeof( CUSTOM_VERTEX));
	device_->SetFVF( D3DFVF_CUSTOM_VERTEX);
	device_->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2);
}